#include "stdafx.h"
#ifdef WIN32

#include<ws2tcpip.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#else
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pthread.h>
typedef int SOCKET;
#endif

#include <stdarg.h>
#include <stdio.h>
#include "trace_worke.h"


static SOCKET m_socketClient;
const char *dataFormat = "{\"opr\" : \"%s\", \"threadId\" : %d, \"line\" : %d, \"fileName\" : \"%s\", \"funcName\" : \"%s\", \"displayLevel\" : %d, \"content\" : \"%s\"}";
CCandy::CCandy(int line, char *file_name, char *func_name, int display_level)
{
	char data[512];	
	CBase::snprintf(data, sizeof(data), dataFormat, "createCandy", CBase::pthread_self(), line, file_name, func_name, display_level, "");

	CTraceWorkManager::instance()->send(data, strlen(data)+1);
	return ;
}

CCandy::~CCandy()
{
	char data[512];	
	CBase::snprintf(data, sizeof(data), dataFormat, "destroyCandy", CBase::pthread_self(), 0, "", "", 0, "");

	CTraceWorkManager::instance()->send(data, strlen(data)+1);
	return ;
}

void CBugKiller::InsertTrace(int line, char *file_name, const char* fmt, ...)
{
	char content[4096];
	va_list ap;
	va_start(ap,fmt);
	CBase::vsnprintf(content,sizeof(content), fmt, ap);
	va_end(ap);

	char data[4096];	
	CBase::snprintf(data, sizeof(data), dataFormat, "insertTrace", CBase::pthread_self(), line, file_name, "", 0, content);
	CTraceWorkManager::instance()->send(data, strlen(data)+1);
	return ;
}

void CBugKiller::InsertHex(int line, char *file_name, char *psBuf, int nBufLen)
{
#if 0
	RECV_DATA *pRecvData = CTimeCalcInfManager::instance()->createRecvData(nBufLen);
	TimeCalcInf *pCalcInf = &pRecvData->calcInf;

	pCalcInf->m_opr = TimeCalcInf::e_insertHex;
	pCalcInf->m_threadId = base::pthread_self();
	pCalcInf->m_line = line;
	pCalcInf->m_fileName = file_name;
	memcpy(pCalcInf->m_pContent, psBuf, nBufLen);

	CTimeCalcInfManager::instance()->pushRecvData(pRecvData);
#endif	
	return ;
}

void CBugKiller::DispAll()
{
	char data[512];	
	CBase::snprintf(data, sizeof(data), dataFormat, "dispAll", CBase::pthread_self(), 0, "", "", 0, "backtrace");

	CTraceWorkManager::instance()->send(data, strlen(data)+1);
}


void CBugKiller::InsertTag(int line, char *file_name, const char* fmt, ...)
{
	char content[4096];
	va_list ap;
	va_start(ap,fmt);
	CBase::vsnprintf(content,sizeof(content), fmt, ap);
	va_end(ap);

	char data[4096];	
	CBase::snprintf(data, sizeof(data), dataFormat, "insertTag", CBase::pthread_self(), line, file_name, "", 0, content);
	CTraceWorkManager::instance()->send(data, strlen(data)+1);
	return ;
}

void CBugKiller::printfMemInfMap()
{
	char data[512];	
	CBase::snprintf(data, sizeof(data), dataFormat, "printfMemInfMap", CBase::pthread_self(), 0, "", "", 0, "");

	CTraceWorkManager::instance()->send(data, strlen(data)+1);
}

void CBugKiller::printfStackInfo(int line, char *file_name)
{
	InsertTrace(line, file_name, "backTrace youself");
}

bool CBugKiller::startServer(const char *sip)
{
	return CTraceWorkManager::instance()->startServer(sip);
}

CTraceWorkManager::CTraceWorkManager()
{
#ifdef WIN32	
		WSADATA wsa={0};
		WSAStartup(MAKEWORD(2,2),&wsa);
#endif
}

CTraceWorkManager *CTraceWorkManager::instance()
{
	static CTraceWorkManager _instance;
	return &_instance;
}

bool CTraceWorkManager::startServer(const char *sip)
{
	m_socketClient = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == m_socketClient)
	{
		return false;
	}

	struct sockaddr_in addr;
	addr.sin_family 		= AF_INET;
	addr.sin_addr.s_addr	= inet_addr(sip);
	addr.sin_port			= htons(8889);
	
	int ret = ::connect(m_socketClient, (struct sockaddr *) & addr, sizeof(sockaddr_in));
	if(-1 == ret)
	{
		return false;
	}
	return true;
}

int CTraceWorkManager::send(char *szText,int len)
{
	int cnt;
	int rc;
	cnt=len;
	while(cnt>0)
	{
		rc=::send(m_socketClient,szText,cnt,0);
		if(rc==SOCKET_ERROR)
		{
			return -1;
		}
		if(rc==0)
		{
			return len-cnt;
		}
		szText+=rc;
		cnt-=rc;
	}
	return len;
}


int CBase::snprintf(char *str, size_t size, const char *format, ...)
{
	va_list ap;
	va_start(ap,format);
#ifdef WIN32
	int ret = vsnprintf_s(str, size, _TRUNCATE, format, ap);
#else
	int ret = ::vsnprintf(str, size, format, ap);
#endif
	va_end(ap);
	return ret;
}

CBase::pthread_t CBase::pthread_self(void)
{
#ifdef WIN32
		return GetCurrentThreadId();
#else
		return ::pthread_self();
#endif

}

int CBase::vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
#ifdef WIN32
	return vsnprintf_s(str, size, _TRUNCATE, format, ap);
#else
	return ::vsnprintf(str, size, format, ap);
#endif
}

int CBase::pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)
{
#ifdef WIN32
	void (*routine)(void *) = (void (*) (void *))start_routine;
	return (int)_beginthread(routine, 0, arg);
#else
	return ::pthread_create(thread, attr, start_routine, arg);
#endif
}

int CBase::usleep(int micro_second)
{
#ifdef WIN32
		if (micro_second < 1000)
		{
			micro_second = 1000;
		}
		
		Sleep(micro_second / 1000);
		return 0;
#else
		return ::usleep(micro_second);
#endif

}


